package com.ydzt.fanka.server.zwcl;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import org.apache.log4j.Logger;

import com.ydzt.fanka.server.domain.BufferRecord;
import com.ydzt.fanka.server.domain.CommunicationNode;
import com.ydzt.fanka.server.init.InitData;
import com.ydzt.fanka.server.persistence.BufferStore;
import com.ydzt.fanka.server.utils.ByteConvert;
import com.ydzt.fanka.server.utils.DBHelper;
import com.ydzt.fanka.server.utils.FileUtil;
import com.ydzt.fanka.server.utils.IOUtil;
import com.ydzt.fanka.server.utils.NetUtil;
import com.ydzt.fanka.server.utils.PackageHelper;

public class ZwclEndDayService {
	List<CommunicationNode> broadcastList = null;
	static Logger logger = Logger.getLogger(ZwclEndDayService.class.getName());
	
	
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
	Connection conn = null;
	byte[] stmtdayByte = null;
	byte[] msgTypeByte = null;
	byte[] msgMgrType = null;
	String msgType = null;
	
	
	
	@SuppressWarnings("unused")
	private boolean createPackageToDroom(List<CommunicationNode> broadcastList,byte[] pkg){
		try{
			if(broadcastList != null){
				for(Iterator<CommunicationNode> it = broadcastList.iterator(); it.hasNext();){
					BufferRecord bufferTmp = new BufferRecord();
					byte[] pkgTmp = pkg;
					CommunicationNode elm = (CommunicationNode)it.next();
					String recevier = elm.getNodeIP();
					int port = elm.getNodePort();
					byte[] recevierIP = ByteConvert.ipv4Address2BinaryArray(recevier);
					if(port > 32767){
						port = port - 65536;
					}
					byte[] recevierPort = ByteConvert.shortToBytes((short)port);
					System.arraycopy(recevierIP, 0, pkgTmp, 6, 4);
					System.arraycopy(recevierPort, 0, pkgTmp, 10, 2);
					bufferTmp.setBufferContent(pkgTmp);
					bufferTmp.setBufferId(UUID.randomUUID().toString());
					if(0 != BufferStore.writePackageIntoBroadcast(bufferTmp)){
						logger.error("将" + bufferTmp.getBufferId() + "写进broadcast文件夹失败");
						return false;
					}
				}
			}
			return true;
		}
		catch(Exception e){
			logger.error("生成广播报文失败!" + e.getMessage());
			return false;
		}
	}
	
	public static void AutoEndDayCentre(){
		logger.info("中心正在执行自动日切....");
		if(DBHelper.setAutoStmtDay()){
			logger.info("中心结算日切换成功");
		}
		else{
			logger.info("中心结算日切换不成功!");
		}
	}
	
	
	/*
	 * 中心日终方法
	 * */
	public void EndDayCentre(){
		byte[] pkg = null;
		stmtdayByte = new byte[4];
		File f = new File(InitData.endflag);
		if(f != null){
			File[] fList = f.listFiles();
			int test = fList.length;
			if(test != 0){
				int count = fList.length;
				//List<String> suppliers = new ArrayList<String>();
				//suppliers = DBHelper.getCompareInfoByteStmtDay();
				if(count > 0){//endflag有数据则开始日终
					logger.info("检查到endflag文件夹中有 " + count + "条日终报文");
					//开始日终操作
					logger.info("开始日终操作");
					File currentFile = f.listFiles()[0];
					try {
						pkg = IOUtil.toByteArrayTraditional(currentFile.getAbsolutePath());
					} catch (IOException e) {
					}
					if(pkg.length == 27){
						logger.info("读取日终报文成功");
						System.arraycopy(pkg, 23, stmtdayByte, 0, 4);
						String stmt_day = ByteConvert.bcd2Str(stmtdayByte);
						logger.info("解析该日终报文的结算日期为:" + stmt_day);
						//将结算控制表中的END_STATE更改为NOW(表示正在进行日终)
						DBHelper.setStmtCtlStatusByType("END_STATE", "NOW");
						//DBHelper.setStmtCtlStatusByType("UPDATE_ACCOUNT_STATE", "NOW");
						logger.info("将结算控制表中的END_STATE更改为NOW");
						//检查数据是否处理完成
						logger.info("开始检查数据是否处理完成");
						File fTmpdata = new File(InitData.tmpdata);
						DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "NOW");
						boolean isCompleta = true;
						while(isCompleta){
							long countBuffer = FileUtil.getlist(fTmpdata);
							logger.info("在tmpdata文件夹中发现  " + countBuffer + " 条数据未处理");
							if(countBuffer == 0){//表示tmpdata文件夹中无文件 文件已经被处理完
								DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "END");
								logger.info("tmpdata文件夹中没有发现未处理的数据");
								isCompleta = false;
								
								//tmpdata处理完成 可以生成当日交易统计
								//logger.info("tmpdata文件夹中数据全部处理完成,将检查卡账户信息更新状态");
								
								//更新卡账户信息检查
								//boolean isNotCompletaAboutUpdateAccountInfo = true;
								
								//在日终的时候 进行卡账户更新
								DBHelper.setStmtCtlStatusByType("UPDATE_ACCOUNT_STATE", "NOW");
								
								/*
								while(isNotCompletaAboutUpdateAccountInfo){
									logger.info("正在检查是否存在未被ZwclUpdateAccountServer处理的明细记录");
									int nonupdateReordCount = DBHelper.getAllNonUpdateDetail();
									
									if(nonupdateReordCount == -1){
										logger.info("查询出错");
									}
									else if(nonupdateReordCount == 0){
										isNotCompletaAboutUpdateAccountInfo = false;
										logger.info("卡账户信息更新完毕");
										DBHelper.setStmtCtlStatusByType("UPDATE_ACCOUNT_STATE", "END");
										logger.info("将进入统计信息生成步骤.");
									}
									else if(nonupdateReordCount >0){
										logger.info("当前存在未进行卡账户更新的明细记录: " + nonupdateReordCount + " 条");
										logger.info("正在进行处理....");
										try {
											Thread.sleep(10000);
										} catch (InterruptedException e) {
										}
									}
								}
								*/
								/*
								logger.info("正在更新卡账户信息...");
								if(0 == DBHelper.updateAccountInfo()){
									logger.info("卡账户信息更新完毕");
									DBHelper.setStmtCtlStatusByType("UPDATE_ACCOUNT_STATE", "END");
									logger.info("将进入统计信息生成步骤.");
								}
								else{
									logger.info("卡账户信息更新出错");
								}
								*/
								//设置统计信息生成为NOW
								DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "NOW");
								if(DBHelper.createStatistics()){
									DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "END");
									logger.info("统计信息生成完毕，将对统计信息进行组包并发送给每一个食堂计算机");
									logger.info("开始对统计信息进行组包......");
									logger.info("获取食堂计算机列表");
									broadcastList = DBHelper.getCommunicationNodeByType("DR");
									logger.info("取得以下通信节点");
									for(int i = 0 ;i < broadcastList.size();i ++){
										CommunicationNode commNode = broadcastList.get(i);
										logger.info(commNode.getNodeID() + "/" + commNode.getNodeName() + "/" + commNode.getNodeIP() + "/" + commNode.getNodePort());
									}
									byte[] pkg3001 = PackageHelper.createPackageAboutStatisticsCentre("01","");
									try {
										if(0 == NetUtil.synSendMsg(pkg3001)){
											logger.info("3001报文已发送");
										}
									} catch (Exception e) {
										
									}
									//this.createPackageToDroom(broadcastList, pkg3001);
									//logger.info("3001报文已放入broadcast文件夹等待广播");
									DBHelper.setStmtCtlStatusByType("END_STATE", "END");
									//结算日期更改为下一天
									if(DBHelper.setStmtDay(stmt_day)){
										logger.info("结算日期已经更新为:" + stmt_day);
										currentFile.delete();//日终完成后 删除唯一的2001报文
										//生成下一结算日的结算控制表记录
										if(DBHelper.createStmtCtlRecordByStmtDay(stmt_day)){
											logger.info("生成下一结算日的结算控制表记录成功");
										}
										else{
											logger.error("生成下一结算日的结算控制表记录失败");
										}
									}
									else{
										logger.error("设置结算日期不成功");
									}
								}
								else{
									logger.error("生成统计信息不成功");
								}
							}
							else{
								logger.info("在tmpdata文件夹内发现有  " + countBuffer + " 个文件未处理！");
								logger.info("正在处理....");
								try {
									Thread.sleep(5000);
								} catch (InterruptedException e) {
								}
							}
						} 
					}
					else{
						logger.info("日终报文长度错误 ! 应当为27长");
					}
				}
				else{
					logger.info("没有在endflag中发现文件");
					/*
					logger.info("存在尚未完成日终的食堂计算机");
					logger.info("当前已经完成上传对账信息的食堂计算机为:");
					for(int i = 0; i < suppliers.size(); i ++){
						logger.info("食堂计算机节点:" + suppliers.get(i).toString());
					}
					*/
				}
			}
			else{
				
			}
		}
	}
	
	
	public void AutoEndDay(){
		byte[] pkg = null;
		stmtdayByte = new byte[4];
		File f = new File(InitData.endflag);
		if(f != null){
			File[] fList = f.listFiles();
			int test = fList.length;
			if(test != 0){
				try {
					int count = f.listFiles().length;
					logger.info("检查到endflag文件夹中有 " + count + "条日终报文");
					logger.info("食堂收到日终报文");
					File currentFile = f.listFiles()[0];
					pkg = IOUtil.toByteArrayTraditional(currentFile.getAbsolutePath());
					logger.info("读取日终报文成功");
					System.arraycopy(pkg, 23, stmtdayByte, 0, 4);
					String stmt_day = ByteConvert.bcd2Str(stmtdayByte);
					logger.info("解析该日终报文的结算日期为:" + stmt_day);
					//将结算控制表中的END_STATE更改为NOW(表示正在进行日终)
					DBHelper.setStmtCtlStatusByType("END_STATE", "NOW");
					logger.info("将结算控制表中的END_STATE更改为NOW");
					//检查数据是否处理完成
					logger.info("开始检查数据是否处理完成");
					File fTmpdata = new File(InitData.tmpdata);
					DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "NOW");
					boolean isCompleta = true;
					while(isCompleta){
						long countBuffer = FileUtil.getlist(fTmpdata);
						logger.info("在tmpdata文件夹中发现  " + countBuffer + " 条数据未处理");
						if(countBuffer == 0){//表示tmpdata文件夹中无文件 文件已经被处理完
							logger.info("tmpdata文件夹中没有发现未处理的数据");
							DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "END");
							isCompleta = false;
							//tmpdata处理完成 可以生成当日交易统计
							logger.info("tmpdata文件夹中数据全部处理完成,将进行统计信息生成");
							//设置统计信息生成为NOW
							DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "NOW");
							if(DBHelper.createStatistics()){
								DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "END");
								
								logger.info("统计信息生成完毕，将对统计信息进行组包并发送至中心");
								logger.info("开始对统计信息进行组包......");
								byte[] pkg3001 = PackageHelper.createPackageAboutStatistics();
								if(0 == NetUtil.synSendMsg(pkg3001)){
									logger.info("3001报文发送成功");
									logger.info("正在本地处理报表数据");
									if(DBHelper.createReportDataCNTREP()){
										DBHelper.setStmtCtlStatusByType("END_STATE", "END");
										//结算日期更改为下一天
										if(DBHelper.setStmtDay(stmt_day)){
											logger.info("结算日期已设置为:" + stmt_day);
											currentFile.delete();//日终完成后 删除唯一的2001报文
											//生成下一结算日的结算控制表记录
											if(DBHelper.createStmtCtlRecordByStmtDay(stmt_day)){
												logger.info("生成下一结算日的结算控制表记录成功");
												
											}
											else{
												logger.error("生成下一结算日的结算控制表记录失败");
											}
										}
										else{
											logger.error("设置结算日期不成功");
										}
									}
									else{
										logger.error("处理报表数据失败");
									}
								}
								else{
									logger.error("发送对账信息不成功");
								}
							}
							else{
								logger.error("生成统计信息不成功");
							}
						}
						else{
							logger.info("在tmpdata文件夹内发现有  " + countBuffer + " 个文件未处理！");
							logger.info("正在处理....");
							Thread.sleep(5000);
						}
					}
				} catch (IOException e) {
				} catch (InterruptedException e) {
				}
				//日终完成(表中stmtday已经修改   endflag文件已经删除)
				//将包头消息类型改写为2002 处理类型改为0x03 发送给中心 
				msgMgrType = new byte[1];
				msgMgrType[0] = 0x03;
				msgTypeByte = new byte[2];
				msgTypeByte = ByteConvert.str2BcdNormal("2002");//
				System.arraycopy(msgTypeByte, 0, pkg, 0, 2);
				System.arraycopy(msgMgrType, 0, pkg, 12, 1);
				try {
					NetUtil.synSendMsg(pkg);
				} catch (Exception e) {
					logger.error("向中心发射通知日终成功报文出错");
					logger.error(e.getMessage());
				}
			}
			else{
				logger.info("没有在endflag中发现文件");
			}
		}
	}
	
	/*
	 * 食堂日终方法
	 * */
	public void EndDay(){
		byte[] pkg = null;
		stmtdayByte = new byte[4];
		File f = new File(InitData.endflag);
		if(f != null){
			File[] fList = f.listFiles();
			int test = fList.length;
			if(test != 0){
				try {
					int count = f.listFiles().length;
					logger.info("检查到endflag文件夹中有 " + count + "条日终报文");
					logger.info("食堂收到日终报文");
					File currentFile = f.listFiles()[0];
					pkg = IOUtil.toByteArrayTraditional(currentFile.getAbsolutePath());
					logger.info("读取日终报文成功");
					System.arraycopy(pkg, 23, stmtdayByte, 0, 4);
					String stmt_day = ByteConvert.bcd2Str(stmtdayByte);
					logger.info("解析该日终报文的结算日期为:" + stmt_day);
					//将结算控制表中的END_STATE更改为NOW(表示正在进行日终)
					DBHelper.setStmtCtlStatusByType("END_STATE", "NOW");
					logger.info("将结算控制表中的END_STATE更改为NOW");
					//检查数据是否处理完成
					logger.info("开始检查数据是否处理完成");
					File fTmpdata = new File(InitData.tmpdata);
					DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "NOW");
					boolean isCompleta = true;
					while(isCompleta){
						long countBuffer = FileUtil.getlist(fTmpdata);
						logger.info("在tmpdata文件夹中发现  " + countBuffer + " 条数据未处理");
						if(countBuffer == 0){//表示tmpdata文件夹中无文件 文件已经被处理完
							logger.info("tmpdata文件夹中没有发现未处理的数据");
							DBHelper.setStmtCtlStatusByType("SPLIT_FLAG", "END");
							isCompleta = false;
							//tmpdata处理完成 可以生成当日交易统计
							logger.info("tmpdata文件夹中数据全部处理完成,将进行统计信息生成");
							//设置统计信息生成为NOW
							DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "NOW");
							if(DBHelper.createStatistics()){
								DBHelper.setStmtCtlStatusByType("STATISTICS_STATE", "END");
								
								logger.info("统计信息生成完毕，将对统计信息进行组包并发送至中心");
								logger.info("开始对统计信息进行组包......");
								byte[] pkg3001 = PackageHelper.createPackageAboutStatistics();
								if(0 == NetUtil.synSendMsg(pkg3001)){
									logger.info("3001报文发送成功");
									logger.info("正在本地处理报表数据");
									if(DBHelper.createReportDataCNTREP()){
										DBHelper.setStmtCtlStatusByType("END_STATE", "END");
										//结算日期更改为下一天
										if(DBHelper.setStmtDay(stmt_day)){
											logger.info("结算日期已设置为:" + stmt_day);
											currentFile.delete();//日终完成后 删除唯一的2001报文
											//生成下一结算日的结算控制表记录
											if(DBHelper.createStmtCtlRecordByStmtDay(stmt_day)){
												logger.info("生成下一结算日的结算控制表记录成功");
												
											}
											else{
												logger.error("生成下一结算日的结算控制表记录失败");
											}
										}
										else{
											logger.error("设置结算日期不成功");
										}
									}
									else{
										logger.error("处理报表数据失败");
									}
								}
								else{
									logger.error("发送对账信息不成功");
								}
							}
							else{
								logger.error("生成统计信息不成功");
							}
						}
						else{
							logger.info("在tmpdata文件夹内发现有  " + countBuffer + " 个文件未处理！");
							logger.info("正在处理....");
							Thread.sleep(5000);
						}
					}
				} catch (IOException e) {
				} catch (InterruptedException e) {
				}
				//日终完成(表中stmtday已经修改   endflag文件已经删除)
				//将包头消息类型改写为2002 处理类型改为0x03 发送给中心 
				msgMgrType = new byte[1];
				msgMgrType[0] = 0x03;
				msgTypeByte = new byte[2];
				msgTypeByte = ByteConvert.str2BcdNormal("2002");//
				System.arraycopy(msgTypeByte, 0, pkg, 0, 2);
				System.arraycopy(msgMgrType, 0, pkg, 12, 1);
				try {
					NetUtil.synSendMsg(pkg);
				} catch (Exception e) {
					logger.error("向中心发射通知日终成功报文出错");
					logger.error(e.getMessage());
				}
			}
			else{
				logger.info("没有在endflag中发现文件");
			}
		}
	}
}
